Skip to content

fix: incorrect tracking of limits after client-side filtering#34

Merged
quettabit merged 1 commit intomainfrom
qb/pf-ign
Apr 14, 2026
Merged

fix: incorrect tracking of limits after client-side filtering#34
quettabit merged 1 commit intomainfrom
qb/pf-ign

Conversation

@quettabit
Copy link
Copy Markdown
Member

No description provided.

@quettabit quettabit changed the title [WIP] fix: incorrect tracking of limits after client-side filtering Apr 14, 2026
@quettabit quettabit marked this pull request as ready for review April 14, 2026 17:38
@quettabit quettabit requested a review from a team as a code owner April 14, 2026 17:38
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 14, 2026

Greptile Summary

This PR fixes a bug where command records were filtered out during proto deserialization (inside read_batch_from_proto) before the session's limit counters (remaining_count, remaining_bytes) and resume pointer (seq_num) were updated, causing the client to undercount consumed records and bytes — and in the worst case (a batch composed entirely of command records) to skip the seq_num advance entirely, risking duplicate delivery on retry.

The fix correctly defers filtering to after all limit-tracking state is applied, adds is_command_record() to SequencedRecord as the canonical check, and suppresses empty post-filter batches from being yielded to callers.

Confidence Score: 5/5

  • Safe to merge; the logic change is correct and consistent across all call sites.
  • All findings are P2 (missing tests). The core fix — moving filtering after limit tracking — is mechanically straightforward and correctly applied in both the session and unary read paths. No blocking issues remain.
  • No files require special attention beyond adding test coverage for the ignore_command_records path.

Important Files Changed

Filename Overview
src/s2_sdk/_s2s/_read_session.py Core fix: limit tracking (seq_num, remaining_count, remaining_bytes) now uses the unfiltered batch before command records are stripped; empty-after-filtering batches are skipped via a new if batch.records: yield batch guard.
src/s2_sdk/_types.py Adds is_command_record() method to SequencedRecord, correctly porting the check len(headers)==1 and headers[0][0]==b"" from the old private _is_command_record helper that operated on the protobuf type.
src/s2_sdk/_mappers.py Simplified read_batch_from_proto by removing the ignore_command_records parameter and the private _is_command_record helper; conversion now consistently delegates to sequenced_record_from_proto.
src/s2_sdk/_ops.py Unary read method updated consistently: converts the full batch first, then filters command records if requested; no limit-tracking state to fix here (single-shot request).

Sequence Diagram

sequenceDiagram
    participant Caller
    participant run_read_session
    participant Server

    Server-->>run_read_session: ReadBatch (data + command records)
    Note over run_read_session: read_batch_from_proto() — full unfiltered batch
    run_read_session->>run_read_session: Update seq_num (last unfiltered record)
    run_read_session->>run_read_session: Decrement remaining_count / remaining_bytes (full batch)
    alt "ignore_command_records=True"
        run_read_session->>run_read_session: Filter out command records
        alt filtered batch has records
            run_read_session-->>Caller: yield ReadBatch (data records only)
        else all records were command records
            Note over run_read_session: batch dropped silently — limits already tracked
        end
    else "ignore_command_records=False"
        run_read_session-->>Caller: yield ReadBatch (all records)
    end
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/s2_sdk/_s2s/_read_session.py
Line: 106-115

Comment:
**No tests cover `ignore_command_records` filtering**

There are no tests exercising the `ignore_command_records=True` path in `run_read_session` — neither the limit-tracking fix (the core bug) nor the suppression of empty post-filter batches. A regression here would be silent. Consider adding at least one unit/integration test that verifies a session with a mix of command and data records correctly decrements `remaining_count`/`remaining_bytes` against the full (unfiltered) record count and only yields batches containing data records.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "initial commit" | Re-trigger Greptile

Comment thread src/s2_sdk/_s2s/_read_session.py
@quettabit quettabit merged commit d69e4f0 into main Apr 14, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant